<?php
/**
 * +--------------------------------------------------------+
 * @Created by PhpStorm.
 * @Category Scheduling.php
 * @Depiction:
 * Author: hwy
 * Date: 2020/12/14  15:27
 * +--------------------------------------------------------+
 */

namespace App\Models;

use App\Exceptions\ResponseException;
use Illuminate\Support\Str;

class Scheduling extends BaseModel
{
    /**
     * @return mixed
     * @throws \Illuminate\Contracts\Container\BindingResolutionException
     * @Depiction
     * @Author hwy
     * @Date  2020/12/14  15:28
     */
    static protected function getKernelEvents()
    {
        app()->make('Illuminate\Contracts\Console\Kernel');

        return app()->make('Illuminate\Console\Scheduling\Schedule')->events();
    }

    /**
     * Get all formatted tasks.
     *
     * @return array
     * @throws \Exception
     *
     */
    static public function getTasks()
    {
        $tasks = [];

        foreach (self::getKernelEvents() as $event) {
            $tasks[] = [
                'task'        => self::formatTask($event),
                'expression'  => $event->expression,
                'nextRunDate' => $event->nextRunDate()->format('Y-m-d H:i:s'),
                'description' => $event->description,
            ];
        }

        $return['data']      = $tasks;
        $return['show_type'] = 1;

        return return_success_msg(ResponseException::REQUEST_SUCCESS_MESSAGE, $return);
    }

    /**
     * Format a giving task.
     *
     * @param $event
     *
     * @return array
     */
    static protected function formatTask($event)
    {
        if ($event instanceof CallbackEvent) {
            return [
                'type' => 'closure',
                'name' => 'Closure',
            ];
        }

        if (Str::contains($event->command, '\'artisan\'')) {
            $exploded = explode(' ', $event->command);

            return [
                'type' => 'artisan',
                'name' => 'artisan ' . implode(' ', array_slice($exploded, 2)),
            ];
        }

        return [
            'type' => 'command',
            'name' => $event->command,
        ];
    }


    public function runTask($id)
    {
        set_time_limit(0);

        /** @var \Illuminate\Console\Scheduling\Event $event */
        $event = $this->getKernelEvents()[$id];

        $event->sendOutputTo($this->getOutputTo());

        $event->run(app());

        return $this->readOutput();
    }

    /**
     * @return string
     */
    protected function getOutputTo()
    {
        if (!$this->sendOutputTo) {
            $this->sendOutputTo = storage_path('app/task-schedule.output');
        }

        return $this->sendOutputTo;
    }

    /**
     * Read output info from output file.
     *
     * @return string
     */
    protected function readOutput()
    {
        return file_get_contents($this->getOutputTo());
    }


}
